package yqRouter

import (
	"fmt"
	"github.com/boj/redistore"
	"github.com/gin-contrib/sessions"
	"github.com/gin-contrib/sessions/cookie"
	"github.com/gin-contrib/sessions/memstore"
	uuid "github.com/satori/go.uuid"
	webEntity "go-yuque/entity"
	"go-yuque/logger"
)

// 决定使用哪种存储方案
var SessionStore = getStoreImpl()

const SessionIdCookieName = "yuqueSessionId"

func getStoreImpl() sessions.Store {

	sessionStoreImpl := webEntity.GetSessionStore()
	var sessionStore sessions.Store = nil

	switch sessionStoreImpl {
	case "cookie":
		// 创建基于cookie的存储引擎，fogiljkdf 参数是用于加密的密钥，可以随便填写
		// 注意，基于 Cookie 的Session存储有长度限制，默认长度为 4096
		sessionStore = cookie.NewStore([]byte("fogiljkdf"))
		logger.Infof("使用基于 cookie 的 Session 存储引擎")
	case "memory":
		// 使用服务器内存存储 Session
		sessionStore = memstore.NewStore([]byte("fogiljkdf"))
		logger.Infof("使用基于 memory 的 Session 存储引擎")
	case "redis":
		// keyPairs 参数必须传入至少一个，用于加密密钥
		// sessionStoreI, err := redis.NewStoreWithDB(10, "tcp", fmt.Sprintf(":%d", webEntity.GetRedisPort()),
		// 	webEntity.GetRedisUsername(), webEntity.GetRedisPw(), webEntity.GetRedisDb(), []byte("fogiljkdf"))
		// if err != nil {
		// 	panic(fmt.Errorf("初始化 redis session 异常 error:%v", err))
		// }
		// sessionStore = sessionStoreI

		sessionStore = createRedisStoreWithDB()

		logger.Infof("使用基于 redis 的 Session 存储引擎")
	}
	// var SessionStore2 = sessions.NewFilesystemStore("sessionStore", []byte("fogiljkdf"))
	return sessionStore
}

// 创建基于 Redis 的 SessionStore
func createRedisStoreWithDB() *store {
	// keyPairs 参数必须传入至少一个，用于加密密钥
	s, err := redistore.NewRediStoreWithDB(10, "tcp", fmt.Sprintf(":%d", webEntity.GetRedisPort()),
		webEntity.GetRedisUsername(), webEntity.GetRedisPw(), webEntity.GetRedisDb(), []byte("fogiljkdf"))
	if err != nil {
		panic(fmt.Errorf("初始化 redis session 异常 error:%v", err))
	}
	// 一切都是为了设置 Session 的 MaxLength，默认是 4KB，不够用
	s.SetMaxLength(0)
	return &store{s}
}

// redis 包里没有导出 Store 结构体，因此自定义
type store struct {
	*redistore.RediStore
}

func (c *store) Options(options sessions.Options) {
	c.RediStore.Options = options.ToGorillaOptions()
}

func sessionGetId(session *sessions.Session) (id string) {
	idI := (*session).Get("__ID")
	if idI != nil && idI != "" {
		id = idI.(string)
	} else {
		id = uuid.NewV4().String()
		(*session).Set("__ID", id)
	}
	return
}
